package remote

import (
	"crypto/md5"
	"encoding/json"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"

	"gitee.com/dark.H/go-remote-repl/datas"
	D "gitee.com/dark.H/go-remote-repl/datas"
	"github.com/Qingluan/Tunnel/tcp"
	"github.com/google/uuid"
	"github.com/schollz/progressbar/v3"
)

func (api *ApiConn) SendFile(name string, data ...datas.Gi) string {
	defer api.Close()
	if _, err := os.Stat(name); err != nil {
		log.Println("file err:", err)
		return ""
	}
	if data != nil {
		if nametest, ok := data[0]["path"]; ok && name == nametest.(string) {
			buf, _ := json.Marshal(data)
			api.SendMsg(string(buf))
		} else {
			log.Println("invalid data: no path found or path's conent != name")
			return ""
		}
	} else {
		log.Println("Sync ready:", name)
		api.SendMsg(name)

	}
	uuidName := api.ReadMsg()

	if uuidName == "" {
		log.Println("uuid file name get err:")
		return ""
	}

	log.Println("Sync ok create file :", uuidName)
	f, err := os.Open(name)
	if err != nil {
		log.Println("read file io err:", err)
		api.Close()
		return ""
	}
	defer f.Close()

	var out io.Writer
	out = api.con
	s, _ := f.Stat()
	len := s.Size()
	bar := progressbar.DefaultBytes(
		len,
		"Upload by api",
		// progressbar.OptionSetBytes(int(len)),
		// progressbar.OptionSetDescription("all size:"+fmt.Sprintf("%.3fkb", float(len)/1024))
	)
	out = io.MultiWriter(out, bar)
	// datas.Copy(api.con, f)
	io.Copy(out, f)
	return uuidName
}

// r: raw_name | s:uuid_name | r: file
func (m *ApiServerMan) RecvFile() {
	defer m.con.Close()
	raw_name := m.ReadMsg()
	m.RecvFileByRawName(raw_name)
}

func (m *ApiServerMan) RecvFileByRawName(raw_name string) {
	defer m.con.Close()
	isAPi := false
	if raw_name == "" {
		return
	} else if strings.HasPrefix(raw_name, "{") && strings.HasSuffix(raw_name, "}") {
		log.Println("---> api")
		dataG := make(D.Gi)
		if err := json.Unmarshal([]byte(raw_name), &dataG); err != nil {
			datas.JsonErr(err, m.con)
			return
		}
		raw_name = dataG["path"].(string)
		log.Println(dataG)
		m.HandleRecvJson(dataG)

		isAPi = true
	} else if strings.HasPrefix(raw_name, "[{") && strings.HasSuffix(raw_name, "}]") {
		log.Println("---> api")
		dataG := make(D.Gi)
		if err := json.Unmarshal([]byte(raw_name[1:len(raw_name)-1]), &dataG); err != nil {
			datas.JsonErr(err, m.con)
			return
		}
		raw_name = dataG["path"].(string)
		log.Println(dataG)
		if m.HandleRecvJson != nil {
			m.HandleRecvJson(dataG)
		} else if DefaultHandleRecvJson != nil {
			DefaultHandleRecvJson(dataG)
		} else {
			log.Println("no handler func seted for handing dataG")
			return
		}
		isAPi = true
	} else {
		log.Println("---> normal:", raw_name)
	}

	space := uuid.UUID{}
	h := uuid.NewHash(md5.New(), space, []byte(raw_name), 1)
	binpath := filepath.Join(os.TempDir(), h.String())
	if isAPi {
		binpath += "rpcapi"
	}
	if strings.Contains(filepath.Base(raw_name), ".") {
		ens := strings.Split(filepath.Base(raw_name), ".")
		binpath += "." + ens[len(ens)-1]
	}
	if _, err := os.Stat(binpath); err == nil {
		os.Remove(binpath)
	}
	m.SendMsg(binpath)
	f, err := os.Create(binpath)
	if err != nil {
		m.SendMsg(err.Error())
		return
	}
	defer f.Close()
	tcp.Copy(f, m.con)
	D.UploadFileManager.UploadedFile(raw_name, binpath)
}
